/**
 * Example 1: Auto-Reset Logic with Manual-Reset Event
 *
 * This example demonstrates the problem that occurs when a module using auto-reset event logic
 * actually receives a manual-reset event. The thread continuously processes the same event
 * because the event is never reset automatically.
 */

#include <Windows.h>
#include <iostream>
#include <string>

// Simulating two separate modules that use the same named event

// Module A: Creates a manual-reset event (first to start)
HANDLE CreateManualResetEvent() {
    std::cout << "Module A: Creating manual-reset event..." << std::endl;
    HANDLE hEvent = CreateEvent(
        NULL,     // Default security attributes
        TRUE,     // Manual-reset event
        FALSE,    // Initial state is nonsignaled
        L"Global\\Example1_Event" // Named event
    );
    
    if (hEvent == NULL) {
        std::cerr << "CreateEvent failed with error " << GetLastError() << std::endl;
        return NULL;
    }
    
    DWORD lastError = GetLastError();
    if (lastError == ERROR_ALREADY_EXISTS) {
        std::cout << "Event already exists! Got handle to existing event." << std::endl;
    }
    
    return hEvent;
}

// Module B: Tries to create an auto-reset event (starts second)
HANDLE CreateAutoResetEvent() {
    std::cout << "Module B: Creating auto-reset event..." << std::endl;
    HANDLE hEvent = CreateEvent(
        NULL,     // Default security attributes
        FALSE,    // Auto-reset event
        FALSE,    // Initial state is nonsignaled
        L"Global\\Example1_Event" // Same named event
    );
    
    if (hEvent == NULL) {
        std::cerr << "CreateEvent failed with error " << GetLastError() << std::endl;
        return NULL;
    }
    
    DWORD lastError = GetLastError();
    if (lastError == ERROR_ALREADY_EXISTS) {
        std::cout << "Event already exists! Got handle to existing event." << std::endl;
        // Note: The auto-reset parameter is ignored, and we get the manual-reset behavior
    }
    
    return hEvent;
}

// Module B thread function that expects auto-reset behavior
DWORD WINAPI AutoResetThreadFunc(LPVOID lpParam) {
    HANDLE hEvent = (HANDLE)lpParam;
    int processCount = 0;
    
    while (processCount < 5) { // Process 5 events and then exit
        std::cout << "Module B thread: Waiting for event signal..." << std::endl;
        DWORD waitResult = WaitForSingleObject(hEvent, INFINITE);
        
        if (waitResult == WAIT_OBJECT_0) {
            processCount++;
            std::cout << "Module B thread: Event signaled! Processing notification #" << processCount << std::endl;
            
            // Logic designed for auto-reset event: no ResetEvent call here
            // In a real auto-reset event, the event would be automatically reset
            // But since the actual event is manual-reset, it stays signaled
            
            std::cout << "Module B thread: Processing complete. Waiting for next event..." << std::endl;
            Sleep(1000); // Simulate some processing time
        }
        else {
            std::cerr << "Wait failed with error " << GetLastError() << std::endl;
            break;
        }
    }
    
    std::cout << "Module B thread: Processed 5 notifications. Exiting thread." << std::endl;
    return 0;
}

int main() {
    std::cout << "Example 1: Auto-Reset Logic in Manual-Reset Event Environment\n" << std::endl;
    
    // First, Module A creates a manual-reset event
    HANDLE hManualEvent = CreateManualResetEvent();
    if (hManualEvent == NULL) {
        return 1;
    }
    
    // Module B tries to create what it thinks is an auto-reset event
    // but actually gets the same manual-reset event
    HANDLE hAutoEvent = CreateAutoResetEvent(); 
    if (hAutoEvent == NULL) {
        CloseHandle(hManualEvent);
        return 1;
    }
    
    // Create a thread for Module B with auto-reset logic
    HANDLE hThread = CreateThread(
        NULL,
        0,
        AutoResetThreadFunc,
        hAutoEvent,
        0,
        NULL
    );
    
    if (hThread == NULL) {
        std::cerr << "CreateThread failed with error " << GetLastError() << std::endl;
        CloseHandle(hManualEvent);
        CloseHandle(hAutoEvent);
        return 1;
    }
    
    // Wait for the thread to start and begin waiting
    Sleep(1000);
    
    // Trigger the event once
    std::cout << "\nMain thread: Signaling the event..." << std::endl;
    if (!SetEvent(hManualEvent)) {
        std::cerr << "SetEvent failed with error " << GetLastError() << std::endl;
    }
    
    // The auto-reset logic thread will process the event multiple times
    // because the event stays signaled (manual-reset behavior)
    std::cout << "Main thread: Event signaled. Module B will process it repeatedly without proper reset." << std::endl;
    
    // Wait for thread to finish (it will process 5 "notifications" and exit)
    WaitForSingleObject(hThread, INFINITE);
    
    std::cout << "\nMain: Demo completed. In a real system, this would cause an infinite processing loop,\n"
              << "     as the auto-reset logic doesn't explicitly reset the manual event." << std::endl;
    
    // Cleanup
    CloseHandle(hThread);
    CloseHandle(hManualEvent);
    CloseHandle(hAutoEvent);
    
    std::cout << "\nPress Enter to exit..." << std::endl;
    std::cin.get();
    
    return 0;
}
